<?php
/**
 * Converters: a library for converting RDFXML, Triples, 
 * Resource Arrays(RDF/JSON),URIs and Qnames
 *
 * @author Keith Alexander
 * @version 0.4
 * @package converters
 **/
/* 
--Changes-- 

---0.25---

fixed some faults in the to_rdfxml() method
changed dependency on arc to arc2

---0.26---

more fault fixing with to_rdfxml() method

---0.27---

fixed rdfxml's handling of blank nodes and extended the GraphIndex->value() method to optionally flatten the object array, and fixed the behaviour when the $namespaces parameter is passed

---0.3---

Added FacetXML->to_array();

---0.4---

added import, reify and dereify methods to GraphIndex

altered Triples::to_resources method to ensure no duplicate triples

added serialiser for Trix and Exhibit

changed SPARQL::to_array to return a SPARQL_Array object, with the data structure the same as sparql/json

*/

/*

Usage:
// 
 $namespaces = array (
    'rdf' => 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
    'sioc' => 'http://rdfs.org/sioc/ns#',
    'dc' => 'http://purl.org/dc/elements/1.1/',
    'terms' => 'http://purl.org/dc/terms/',
    'foaf' => 'http://xmlns.com/foaf/spec/',
    'rdfs' => 'http://www.w3.org/2000/01/rdf-schema#',
    'rss' => 'http://purl.org/rss/1.0/',
    'owl' => 'http://www.w3.org/2002/07/owl#',
    'rel' => 'http://purl.org/vocab/relationship/',
    'ibis' => 'http://dannyayers.com/2003/12/ibis.rdfs#',
    'doap' => 'http://usefulinc.com/ns/doap#',
    'frbr' => 'http://purl.org/vocab/frbr/core#',
  );

   // you can optionally pass in an array of namespace prefixes 
   // when you initiate the Convertor class.
   // Alternatively (or as well), you can supply namespaces as a 
   //  second parameter to methods that can (or need to) use prefixes (such as to_qname())

	//the RDFXML converter needs the ARC RDF/XML parser, available from:
	//	http://arc.web-semantics.org/download
	
	$arc_rdfxml_parser_location = 'arc/Arc_rdfxml_parser.php';
	
	$Converter = new Converter($namespaces, $arc_rdfxml_parser_location);
	$ResourcesObject = $Converter->RDFXML->to_resources($rdfxml_string);
	$resources_assoc_array = $ResourcesObject->value();
	$resources_assoc_array ==  array(
		'http://example.org/test/JohnSmith'=>
			array(
				'http://xmlns.com/foaf/spec/name' => 	
						array(
								array('type'=>'literal','value'=>'John Smith')
							),
				'http://xmlns.com/foaf/spec/mbox' => array(
									array('type'=>'uri','value'=>'mailto:john@example.org')
							),	
				'http://www.w3.org/2000/01/rdf-schema#label' => array(
							array('type'=>'literal','value'=>'Label','lang'=>'en-gb')
							),	
				),

		); // true
	
	$ResourceObject = $ResourcesObject->to_resource('http://example.org/test/JohnSmith');
	$ResourcesObject->get_title() == 'John Smith'; // true
	
	$Convert->URI->to_qname('http://xmlns.com/foaf/spec/name')->value() == 'foaf:name'; //true
	$Convert->URI->to_term('http://xmlns.com/foaf/spec/name') == 'name'; //true
*/

/**
 * Converter
 *
 * @package converters
 * @author Keith Alexander
 **/
class Converter
{
	var $namespaces = array();
	// var $RDFXML;
	// var $Triples;
	// var $GraphIndex;
	// var $SPARQL_XML;
	// var $Qname;
	// var $URI;
	// var $FormArray;
	// var $FacetXML;
	// var $GraphIndex;

	/**
	 * Converter::__construct(array $namespaces, string $arc_rdf_parser_location)
	 *
	 * @return void
	 * @author Keith Alexander
	 **/
	function __construct($namespaces=array(), $arc_rdf_parser_location='lib/ARC/ARC2.php')
	{
		require_once($arc_rdf_parser_location);
		$this->namespaces = $namespaces;
		// foreach(array('RDFXML','Triples','GraphIndex','GraphIndex','SPARQL_XML','Qname','URI','FormArray', 'FacetXML') as $Object)
		// {
		// 	$this->$Object = new $Object();
		// 	$this->$Object->set_namespaces($namespaces);
		// 	$this->$Object->set_container($this);
		// }
	}
	
	function __get($prop){
		if(in_array($prop, array('RDFXML','Triples','GraphIndex','SPARQL_XML','Qname','URI','FormArray', 'FacetXML') ) AND !isset($this->$prop)){
			require_once($prop.'.class.php');
			$this->$prop = new $prop();
			$this->$prop->set_namespaces($this->namespaces);
			$this->$prop->set_container($this);			
		}
		return $this->$prop;
	}
	
}
/**
 * ConvertableObject
 *
 * @package converters
 * @author Keith Alexander
 **/
class ConvertableObject
{
	/**
	 * containerObject  - a reference to the Converter object
	 * that provides access to ConvertableObjects
	 * 
	 * @access protected
	 * @var object
	 **/
	 protected $containerObject;
	/**
	 * the underlying data encapsulated by the object
	 *
	 * @var string|array
	 **/
	var $value;
	/**
	 * namespaces - an associative array of prefix => uri
	 *
	 * @var array
	 **/
	var $namespaces = array();
	
	
	const DC = 'http://purl.org/dc/elements/1.1/';
	const RDFS = 'http://www.w3.org/2000/01/rdf-schema#';
	const FOAF = 'http://xmlns.com/foaf/0.1/';
	const FOAF_SPEC = 'http://xmlns.com/foaf/spec/';
	const RDF = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#';
	const XSD = 'http://www.w3.org/2001/XMLSchema#';
	const RSS = 'http://purl.org/rss/1.0/';
	const OWL = 'http://www.w3.org/2002/07/owl#';
	const TERMS = 'http://purl.org/dc/terms/';
	
	function __construct($value=false, $containerObject=false)
	{
		if($value) $this->set_value($value);		
		if($containerObject) $this->set_container($containerObject);
	}
	
	function set_container(&$containerObject)
	{
		$this->containerObject = $containerObject;
	}
	function set_value($val)
	{
		$this->value = $val;
	}
	
	/**
	 * gets the value of the data object
	 *
	 * @return string|array
	 * @author Keith Alexander
	 **/
	public function value()
	{
		return $this->value;
	}
	/**
	 * gets the namespaces associative array
	 *
	 * @return array
	 * @author Keith Alexander
	 **/
	function namespaces()
	{
		if(isset($this->containerObject)) return $this->containerObject->namespaces;
		else return $this->namespaces;
	}
	
	/**
	 * add_namespace
	 *
	 * @param string $prefix 
	 * @param string $namespace 
	 * @param string $count 
	 * @return void
	 * @author Keith Alexander
	 * 
	 * adds a prefix => namespace mapping if it is not already present - if it is present, a new prefix is invented by adding a number to the end
	 */
	
	function add_namespace($prefix, $namespace, $count=1)
	{
		if(!isset($this->namespaces[$prefix]) OR $this->namespaces[$prefix] == $namespace)
		{
			$this->namespaces[$prefix] = $namespace;
		} 
		else if(!isset($this->namespaces[$prefix.$count])) 
		{
			$prefix = $prefix.$count;
			$this->namespaces[$prefix] = $namespace;	
		}
		else 
		{
			$prefix = $this->add_namespace($prefix, $namespace, ++$count);
		}
		return $prefix;
	}
	
	/**
	 * sets the namespaces array property
	 *
	 * @return void
	 * @author Keith Alexander
	 **/
	function set_namespaces($namespaces)
	{
		foreach($namespaces as $p => $n) $this->add_namespace($p,$n);
		if(isset($this->containerObject))
		{
			$this->containerObject->namespaces = $namespaces;
		}
	}
}


/* Autoload Class Files as needed*/
// if(!function_exists('__autoload')){
// 	$autoload = <<<_PHP_
// 	function __autoload(\$classname){
// 		
// 		\$filename = (\$classname).'.class.php';
// 		
// 		if(in_array(\$filename, scandir('./'))){
// 			require_once(\$filename);			
// 		}
// 
// 	}
// _PHP_;
// 	eval($autoload);
// }
?>